<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.0.0">
  <link rel="icon" type="image/png" sizes="32x32" href="/img/favicon.ico">
  <link rel="icon" type="image/png" sizes="16x16" href="/img/favicon.ico">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css">


<script id="hexo-configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    hostname: new URL('https://cxyzjp.gitee.io').hostname,
    root: '/',
    scheme: 'Pisces',
    version: '7.6.0',
    exturl: true,
    sidebar: {"position":"left","display":"post","offset":12,"onmobile":true},
    copycode: {"enable":false,"show_result":false,"style":null},
    back2top: {"enable":true,"sidebar":false,"scrollpercent":true},
    bookmark: {"enable":false,"color":"#222","save":"auto"},
    fancybox: false,
    mediumzoom: true,
    lazyload: true,
    pangu: false,
    algolia: {
      appID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    },
    localsearch: {"enable":true,"trigger":"auto","top_n_per_article":1,"preload":true},
    path: 'search.json',
    motion: {"enable":false}
  };
</script>

  <meta name="description" content="面试遇到分布式锁的相关问题，借鉴网上资料做了一些总结。 分布式锁经典的 CAP 理论提到任何一个系统都无法同时满足一致性（Consistency）、可用性（Availability）和分区容错性（Partition tolerance）三者的，同一时刻只能满足两个，在这种情况下分布式锁就出现了，分布式锁就是用来解决数据一致性问题的。 分布式锁就是在分布式环境下用来解决多实例对数据访问一致性的一种技">
<meta name="keywords" content="分布式">
<meta property="og:type" content="article">
<meta property="og:title" content="分布式锁">
<meta property="og:url" content="https:&#x2F;&#x2F;cxyzjp.gitee.io&#x2F;distributed&#x2F;distributed-lock&#x2F;index.html">
<meta property="og:site_name" content="程序员的日常">
<meta property="og:description" content="面试遇到分布式锁的相关问题，借鉴网上资料做了一些总结。 分布式锁经典的 CAP 理论提到任何一个系统都无法同时满足一致性（Consistency）、可用性（Availability）和分区容错性（Partition tolerance）三者的，同一时刻只能满足两个，在这种情况下分布式锁就出现了，分布式锁就是用来解决数据一致性问题的。 分布式锁就是在分布式环境下用来解决多实例对数据访问一致性的一种技">
<meta property="og:locale" content="zh-CN">
<meta property="og:updated_time" content="2019-12-14T02:29:10.000Z">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="https://cxyzjp.gitee.io/distributed/distributed-lock/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome: false,
    isPost: true,
    isPage: false,
    isArchive: false
  };
</script>

  <title>分布式锁 | 程序员的日常</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-meta">

    <div>
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">程序员的日常</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
        <h1 class="site-subtitle" itemprop="description">自强不息</h1>
      
  </div>

  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>
</div>


<nav class="site-nav">
  
  <ul id="menu" class="menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-fw fa-home"></i>首页</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-fw fa-archive"></i>归档<span class="badge">5</span></a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-fw fa-tags"></i>标签<span class="badge">6</span></a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>

</nav>
  <div class="site-search">
    <div class="popup search-popup">
    <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocorrect="off" autocapitalize="none"
           placeholder="搜索..." spellcheck="false"
           type="text" id="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result"></div>

</div>
<div class="search-pop-overlay"></div>

  </div>
</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content">
            

  <div class="posts-expand">
      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block " lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://cxyzjp.gitee.io/distributed/distributed-lock/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/img/avatar.jpg">
      <meta itemprop="name" content="CXYZJP">
      <meta itemprop="description" content="记录生活中的点点滴滴">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="程序员的日常">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          分布式锁
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2019-12-13 14:16:49" itemprop="dateCreated datePublished" datetime="2019-12-13T14:16:49+08:00">2019-12-13</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2019-12-14 10:29:10" itemprop="dateModified" datetime="2019-12-14T10:29:10+08:00">2019-12-14</time>
              </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <p>面试遇到分布式锁的相关问题，借鉴网上资料做了一些总结。</p>
<h1 id="分布式锁"><a href="#分布式锁" class="headerlink" title="分布式锁"></a>分布式锁</h1><p>经典的 CAP 理论提到任何一个系统都无法同时满足一致性（Consistency）、可用性（Availability）和分区容错性（Partition tolerance）三者的，同一时刻只能满足两个，在这种情况下分布式锁就出现了，分布式锁就是用来解决数据一致性问题的。</p>
<p>分布式锁就是在分布式环境下用来解决多实例对数据访问一致性的一种技术方案。</p>
<h1 id="分布式锁的特性"><a href="#分布式锁的特性" class="headerlink" title="分布式锁的特性"></a>分布式锁的特性</h1><p>1、在分布式系统环境下，一个方法在同一时间只能被一个机器的一个线程执行；<br>2、高可用的获取锁与释放锁；<br>3、高性能的获取锁与释放锁；<br>4、具备可重入特性；<br>5、具备锁失效机制，防止死锁；<br>6、具备非阻塞锁特性，即没有获取到锁将直接返回获取锁失败。</p>
<a id="more"></a>

<h1 id="实现方式"><a href="#实现方式" class="headerlink" title="实现方式"></a>实现方式</h1><h2 id="基于数据库方式"><a href="#基于数据库方式" class="headerlink" title="基于数据库方式"></a>基于数据库方式</h2><p>实现都需要一个额外的表，并且要有一个唯一索引字段</p>
<h3 id="阻塞式"><a href="#阻塞式" class="headerlink" title="阻塞式"></a>阻塞式</h3><figure class="highlight sql"><table><tr><td class="code"><pre><span class="line"><span class="keyword">select</span> xxx <span class="keyword">for</span> <span class="keyword">update</span></span></pre></td></tr></table></figure>
<p>1、需要关闭事务的自动提交</p>
<p>2、执行 SQL 去获得锁，如果获得锁成功，执行下面的业务逻辑，如果这里没有获取到锁，则会阻塞，一直等待。</p>
<p>3、业务执行结束后，手动提交事务。这里如果程序在执行提交事务失败，异常或者服务宕机后，数据库会自动释放锁，以免导致死锁。</p>
<p>4、但是这里有个问题就是如果在高并发的情况下，很多线程都没有获得到锁，都在阻塞等待，这样会导致数据库的服务器压力过大，会影响数据库的服务。</p>
<p><strong>拓展：</strong><br>InnoDB 预设是Row-Level Lock，所以只有条件指定主键，MySQL 才会执行Row lock (只锁住被选取的数据) ，否则MySQL 将会执行Table Lock (将整个数据表单给锁住)。</p>
<p><strong>示例：</strong></p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">set autocommit&#x3D;0;</span></pre></td></tr><tr><td class="code"><pre><span class="line">&#x2F;&#x2F;设置完autocommit后，我们就可以执行我们的正常业务了。具体如下：</span></pre></td></tr><tr><td class="code"><pre><span class="line">&#x2F;&#x2F;0.开始事务</span></pre></td></tr><tr><td class="code"><pre><span class="line">begin;&#x2F;begin work;&#x2F;start transaction; (三者选一就可以)</span></pre></td></tr><tr><td class="code"><pre><span class="line">&#x2F;&#x2F;1.查询出商品信息</span></pre></td></tr><tr><td class="code"><pre><span class="line">select status from t_goods where id&#x3D;1 for update;</span></pre></td></tr><tr><td class="code"><pre><span class="line">&#x2F;&#x2F;2.根据商品信息生成订单</span></pre></td></tr><tr><td class="code"><pre><span class="line">insert into t_orders (id,goods_id) values (null,1);</span></pre></td></tr><tr><td class="code"><pre><span class="line">&#x2F;&#x2F;3.修改商品status为2</span></pre></td></tr><tr><td class="code"><pre><span class="line">update t_goods set status&#x3D;2;</span></pre></td></tr><tr><td class="code"><pre><span class="line">&#x2F;&#x2F;4.提交事务</span></pre></td></tr><tr><td class="code"><pre><span class="line">commit;&#x2F;commit work;</span></pre></td></tr></table></figure>

<h3 id="非阻塞式"><a href="#非阻塞式" class="headerlink" title="非阻塞式"></a>非阻塞式</h3><figure class="highlight sql"><table><tr><td class="code"><pre><span class="line"><span class="keyword">insert</span> <span class="keyword">into</span> xxx</span></pre></td></tr><tr><td class="code"><pre><span class="line"><span class="keyword">delete</span> <span class="keyword">from</span></span></pre></td></tr></table></figure>
<p>1、向指定的表中插入一条唯一索引的数据，插入成功则表示获得锁，否则未获得</p>
<p>2、成功获得的锁后就可以执行业务逻辑，在执行完业务逻辑后就可以删除执行的记录。</p>
<p><strong>存在问题：</strong><br>1、不具备阻塞锁特性，获取不到锁直接返回失败，所以需要优化获取逻辑，循环多次去获取。</p>
<p>2、没有锁失效机制，因为有可能出现成功插入数据后，服务器宕机了，对应的数据没有被删除，当服务恢复后一直获取不到锁，所以，需要在表中新增一列，用于记录失效时间，并且需要有定时任务清除这些失效的数据</p>
<p>3、不具备可重入的特性，因为同一个线程在释放锁之前，行数据一直存在，无法再次成功插入数据，所以，需要在表中新增一列，用于记录当前获取到锁的机器和线程信息，在再次获取锁的时候，先查询表中机器和线程信息是否和当前机器和线程相同，若相同则直接获取锁</p>
<h3 id="数据库实现的优缺点"><a href="#数据库实现的优缺点" class="headerlink" title="数据库实现的优缺点"></a>数据库实现的优缺点</h3><p><strong>优点:</strong><br>容易理解和实现</p>
<p><strong>缺点：</strong><br>1、基于数据库实现的，数据库的可用性和性能将直接影响分布式锁的可用性及性能，所以，数据库需要双机部署、数据同步、主备切换<br>2、在实施的过程中会遇到各种不同的问题，为了解决这些问题，实现方式将会越来越复杂；依赖数据库需要一定的资源开销，性能问题需要考虑<br>3、数据库的行锁会因为 MySQL 的查询优化而失效</p>
<h2 id="基于Redis方式"><a href="#基于Redis方式" class="headerlink" title="基于Redis方式"></a>基于Redis方式</h2><h3 id="实现"><a href="#实现" class="headerlink" title="实现"></a>实现</h3><p>1、利用setnx(set if not exists)和expire过期时间来实现<br>2、set的value是随机数，删除锁时判断加锁和解锁是同一个线程</p>
<p><strong>示例代码：</strong></p>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 获取锁</span></span></pre></td></tr><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">tryLock</span><span class="params">(String lockKey, String value)</span> </span>&#123;</span></pre></td></tr><tr><td class="code"><pre><span class="line">    <span class="keyword">return</span> jedis.set(lockKey, value, <span class="string">'NX'</span>, <span class="string">'EX'</span>, <span class="number">5</span>);</span></pre></td></tr><tr><td class="code"><pre><span class="line">&#125;</span></pre></td></tr><tr><td class="code"><pre><span class="line"><span class="comment">// 释放锁</span></span></pre></td></tr><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">unLock</span><span class="params">(String lockKey, String value)</span> </span>&#123;</span></pre></td></tr><tr><td class="code"><pre><span class="line">    String script = <span class="string">"if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"</span>;</span></pre></td></tr><tr><td class="code"><pre><span class="line">    Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(value));</span></pre></td></tr><tr><td class="code"><pre><span class="line">&#125;</span></pre></td></tr></table></figure>

<p><strong>可重入性</strong><br>Redis 分布式锁如果要支持可重入，需要对客户端的 set 方法进行包装，使用线程的 Threadlocal 变量存储当前持有锁的计数。</p>
<p><strong>拓展：</strong><br><strong>Redlock 算法</strong><br>存在问题：集群中，主节点挂掉时，从节点会取而代之，客户端上却并没有明显感知。原先第一个客户端在主节点中申请成功了一把锁，但是这把锁还没有来得及同步到从节点，主节点突然挂掉了。然后从节点变成了主节点，这个新的节点内部没有这个锁，所以当另一个客户端过来请求加锁时，立即就批准了。这样就会导致系统中同样一把锁被两个客户端同时持有，不安全性由此产生。<br>Redlock解决：加锁时，它会向过半节点发送 set(key, value, nx=True, ex=xxx) 指令，只要过半节点 set 成功，那就认为加锁成功。释放锁时，需要向所有节点发送 del 指令。</p>
<p><strong>Spring实现</strong><br>Spring Integration提供的全局锁目前为如下存储提供了实现，Gemfire、JDBC、Redis、Zookeeper</p>
<figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span></pre></td></tr><tr><td class="code"><pre><span class="line">  <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.boot<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span></pre></td></tr><tr><td class="code"><pre><span class="line">  <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-boot-starter-integration<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span></pre></td></tr><tr><td class="code"><pre><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span></pre></td></tr><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span></pre></td></tr><tr><td class="code"><pre><span class="line">  <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.integration<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span></pre></td></tr><tr><td class="code"><pre><span class="line">  <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-integration-redis<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span></pre></td></tr><tr><td class="code"><pre><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 配置类</span></span></pre></td></tr><tr><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span></pre></td></tr><tr><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">RedisLockConfiguration</span> </span>&#123;</span></pre></td></tr><tr><td class="code"><pre><span class="line">  <span class="meta">@Bean</span></span></pre></td></tr><tr><td class="code"><pre><span class="line">  <span class="function"><span class="keyword">public</span> RedisLockRegistry <span class="title">redisLockRegistry</span><span class="params">(RedisConnectionFactory redisConnectionFactory)</span> </span>&#123;</span></pre></td></tr><tr><td class="code"><pre><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> RedisLockRegistry(redisConnectionFactory, <span class="string">"spring-cloud"</span>);</span></pre></td></tr><tr><td class="code"><pre><span class="line">  &#125;</span></pre></td></tr><tr><td class="code"><pre><span class="line">&#125;</span></pre></td></tr><tr><td class="code"><pre><span class="line"></span></pre></td></tr><tr><td class="code"><pre><span class="line"><span class="comment">// 使用</span></span></pre></td></tr><tr><td class="code"><pre><span class="line">Lock lock = redisLockRegistry.obtain(<span class="string">"lock"</span>);</span></pre></td></tr><tr><td class="code"><pre><span class="line">lock.tryLock(<span class="number">3</span>, TimeUnit.SECONDS);</span></pre></td></tr></table></figure>

<h3 id="Redis实现的优缺点"><a href="#Redis实现的优缺点" class="headerlink" title="Redis实现的优缺点"></a>Redis实现的优缺点</h3><p><strong>优点：</strong></p>
<ol>
<li>实现简单；</li>
<li>理解逻辑简单；</li>
<li>性能好，毕竟是缓存。</li>
</ol>
<p><strong>缺点：</strong></p>
<ol>
<li>Redis 容易单点故障，集群部署；</li>
<li>key 的过期时间设置多少不明确，只能根据实际情况调整</li>
</ol>
<h2 id="基于ZooKeeper方式"><a href="#基于ZooKeeper方式" class="headerlink" title="基于ZooKeeper方式"></a>基于ZooKeeper方式</h2><p>ZooKeeper是一个为分布式应用提供一致性服务的开源组件，它内部是一个分层的文件系统目录树结构，规定同一个目录下只能有一个唯一文件名</p>
<h3 id="实现-1"><a href="#实现-1" class="headerlink" title="实现"></a>实现</h3><p>1、创建锁目录lock<br>2、在lock下创建临时顺序节点；<br>3、获取lock目录下所有的子节点，然后获取比自己小的兄弟节点，如果不存在，则说明当前线程顺序号最小，获得锁；<br>4、其他线程判断自己不是最小节点，设置监听比自己次小的节点；<br>5、线程处理完，删除自己的节点，其他线程监听到变更事件，判断自己是不是最小的节点，如果是则获得锁。</p>
<p><strong>轮子</strong><br>1、Curator 是一个 ZK 的开源客户端，也提供了分布式锁的实现<br>2、<span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL3R3aXR0ZXIvY29tbW9ucy9ibG9iL21hc3Rlci9zcmMvamF2YS9jb20vdHdpdHRlci9jb21tb24vem9va2VlcGVyL0Rpc3RyaWJ1dGVkTG9ja0ltcGwuamF2YQ==" title="https://github.com/twitter/commons/blob/master/src/java/com/twitter/common/zookeeper/DistributedLockImpl.java">twitter例子<i class="fa fa-external-link"></i></span></p>
<h3 id="ZooKeeper实现的优缺点"><a href="#ZooKeeper实现的优缺点" class="headerlink" title="ZooKeeper实现的优缺点"></a>ZooKeeper实现的优缺点</h3><p><strong>优点：</strong><br>1、具备可重入、阻塞锁特性，可解决失效死锁问题。<br>2、ZK本身就是集群部署，高可用。</p>
<p><strong>缺点：</strong><br>1、实现较为复杂；<br>2、非缓存机制，大量频繁创建删除节点会影响ZK集群性能；</p>

    </div>

    
    
    

      <footer class="post-footer">
          <div class="post-tags">
              <a href="/tags/%E5%88%86%E5%B8%83%E5%BC%8F/" rel="tag"># 分布式</a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/SpringBoot/ShardingJDBC/" rel="prev" title="SpringBoot集成Sharding-JDBC">
      <i class="fa fa-chevron-left"></i> SpringBoot集成Sharding-JDBC
    </a></div>
      <div class="post-nav-item">
    <a href="/mac/Homebrew/" rel="next" title="Homebrew">
      Homebrew <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  

  </div>


          </div>
          

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#分布式锁"><span class="nav-number">1.</span> <span class="nav-text">分布式锁</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#分布式锁的特性"><span class="nav-number">2.</span> <span class="nav-text">分布式锁的特性</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#实现方式"><span class="nav-number">3.</span> <span class="nav-text">实现方式</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#基于数据库方式"><span class="nav-number">3.1.</span> <span class="nav-text">基于数据库方式</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#阻塞式"><span class="nav-number">3.1.1.</span> <span class="nav-text">阻塞式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#非阻塞式"><span class="nav-number">3.1.2.</span> <span class="nav-text">非阻塞式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#数据库实现的优缺点"><span class="nav-number">3.1.3.</span> <span class="nav-text">数据库实现的优缺点</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#基于Redis方式"><span class="nav-number">3.2.</span> <span class="nav-text">基于Redis方式</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#实现"><span class="nav-number">3.2.1.</span> <span class="nav-text">实现</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Redis实现的优缺点"><span class="nav-number">3.2.2.</span> <span class="nav-text">Redis实现的优缺点</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#基于ZooKeeper方式"><span class="nav-number">3.3.</span> <span class="nav-text">基于ZooKeeper方式</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#实现-1"><span class="nav-number">3.3.1.</span> <span class="nav-text">实现</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#ZooKeeper实现的优缺点"><span class="nav-number">3.3.2.</span> <span class="nav-text">ZooKeeper实现的优缺点</span></a></li></ol></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="CXYZJP"
      src="/img/avatar.jpg">
  <p class="site-author-name" itemprop="name">CXYZJP</p>
  <div class="site-description" itemprop="description">记录生活中的点点滴滴</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">5</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">6</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2N4eXpqcA==" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;cxyzjp"><i class="fa fa-fw fa-github"></i></span>
      </span>
      <span class="links-of-author-item">
        <span class="exturl" data-url="bWFpbHRvOjMyODEwODIyM0BxcS5jb20=" title="E-Mail → mailto:328108223@qq.com"><i class="fa fa-fw fa-envelope"></i></span>
      </span>
  </div>


  <div class="links-of-blogroll motion-element">
    <div class="links-of-blogroll-title">
      <i class="fa fa-fw fa-link"></i>
      友情链接
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <span class="exturl" data-url="aHR0cDovL2N4eXpqcC5jbg==" title="http:&#x2F;&#x2F;cxyzjp.cn">个人主页</span>
        </li>
        <li class="links-of-blogroll-item">
          <span class="exturl" data-url="aHR0cHM6Ly9naXRlZS5jb20vY3h5empwL2N4eXpqcC9wYWdlcw==" title="https:&#x2F;&#x2F;gitee.com&#x2F;cxyzjp&#x2F;cxyzjp&#x2F;pages">Gitee Pages</span>
        </li>
    </ul>
  </div>

      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

<div class="copyright">
  
  &copy; 2018 – 
  <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">CXYZJP</span>
</div>
  <div class="powered-by">由 <span class="exturl theme-link" data-url="aHR0cHM6Ly9oZXhvLmlv">Hexo</span> 强力驱动
  </div>
  <span class="post-meta-divider">|</span>
  <div class="theme-info">主题 – <span class="exturl theme-link" data-url="aHR0cHM6Ly9waXNjZXMudGhlbWUtbmV4dC5vcmc=">NexT.Pisces</span>
  </div>

        








        
      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/medium-zoom@1/dist/medium-zoom.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/lozad@1/dist/lozad.min.js"></script>
<script src="/js/utils.js"></script>
<script src="/js/schemes/pisces.js"></script>
<script src="/js/next-boot.js"></script>



  




  <script src="/js/local-search.js"></script>













  

  

  

</body>
</html>
